home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / editors / pur_c_vi.zoo / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-13  |  9.5 KB  |  456 lines

  1. /*
  2.  * STEVIE - ST Editor for VI Enthusiasts   ...Tim Thompson...twitch!tjt...
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include "stevie.h"
  8.  
  9. #ifdef ATARI
  10. #include <osbind.h>
  11. #endif
  12.  
  13. int Rows;        /* Number of Rows and Columns */
  14. int Columns;        /* in the current window. */
  15.  
  16. char *Realscreen;    /* What's currently on the screen, a single */
  17.             /* array of size Rows*Columns. */
  18. char *Nextscreen;    /* What's to be put on the screen. */
  19.  
  20. char *Filename = NULL;    /* Current file name */
  21.  
  22. char *Filemem;        /* The contents of the file, as a single array. */
  23.  
  24. char *Filemax;        /* Pointer to the end of allocated space for */
  25.             /* Filemem. (It points to the first byte AFTER */
  26.             /* the allocated space.) */
  27.  
  28. char *Fileend;        /* Pointer to the end of the file in Filemem. */
  29.             /* (It points to the byte AFTER the last byte.) */
  30.  
  31. char *Topchar;        /* Pointer to the byte in Filemem which is */
  32.             /* in the upper left corner of the screen. */
  33.  
  34. char *Botchar;        /* Pointer to the byte in Filemem which is */
  35.             /* just off the bottom of the screen. */
  36.  
  37. char *Curschar;        /* Pointer to byte in Filemem at which the */
  38.             /* cursor is currently placed. */
  39.  
  40. int Cursrow, Curscol;    /* Current position of cursor */
  41.  
  42. int Cursvcol;        /* Current virtual column, the column number of */
  43.             /* the file's actual line, as opposed to the */
  44.             /* column number we're at on the screen.  This */
  45.             /* makes a difference on lines that span more */
  46.             /* than one screen line. */
  47.  
  48. int State = NORMAL;    /* This is the current state of the command */
  49.             /* interpreter. */
  50.  
  51. int Prenum = 0;        /* The (optional) number before a command. */
  52.  
  53. char *Insstart;        /* This is where the latest insert/append */
  54.             /* mode started. */
  55.  
  56. int Changed = 0;    /* Set to 1 if something in the file has been */
  57.             /* changed and not written out. */
  58.  
  59. int Debug = 0;
  60.  
  61. int Binary = 0;        /* Set to 1 if the file should be read and written */
  62.             /* in binary mode (no cr-lf translation). */
  63.  
  64. char Redobuff[1024];    /* Each command should stuff characters into this */
  65.             /* buffer that will re-execute itself. */
  66.  
  67. char Undobuff[1024];    /* Each command should stuff characters into this */
  68.             /* buffer that will undo its effects. */
  69.  
  70. char Insbuff[1024];    /* Each insertion gets stuffed into this buffer. */
  71.  
  72. char *Uncurschar = NULL;/* Curschar is restored to this before undoing. */
  73.  
  74. int Ninsert = 0;    /* Number of characters in the current insertion. */
  75. int Undelchars = 0;    /* Number of characters to delete, when undoing. */
  76. char *Insptr = NULL;
  77.  
  78. main(argc,argv)
  79. int argc;
  80. char **argv;
  81. {
  82.     int mode = 8;
  83.  
  84.     while ( argc>1 && argv[1][0] == '-' ) {
  85.         switch (argv[1][1]) {
  86.         case 'x':
  87.             mode = 16;
  88.             break;
  89.         case 'o':
  90.             mode = 8;
  91.             break;
  92.         case 'd':
  93.             Debug = 1;
  94.             break;
  95.         case 'b':
  96.             Binary = 1;
  97.             break;
  98.         }
  99.         argc--;
  100.         argv++;
  101.     }
  102.  
  103.     if ( argc <= 1 ) {
  104.         fprintf(stderr,"usage: stevie {file}\n");
  105.         exit(1);
  106.     }
  107.  
  108.     Filename = strsave(argv[1]);
  109.  
  110.     windinit();
  111.  
  112.     /* Make sure Rows/Columns are big enough */
  113.     if ( Rows < 3 || Columns < 16 ) {
  114.         fprintf(stderr,"Rows=%d Columns=%d not big enough!\n",
  115.             Rows,Columns);
  116.         windexit(0);
  117.     }
  118.  
  119.     switch ( mode ) {
  120.     case 8:
  121.         octchars();
  122.         break;
  123.     case 16:
  124.         hexchars();
  125.         break;
  126.     }
  127.  
  128.     screenalloc();
  129.     filealloc();
  130.  
  131.     screenclear();
  132.  
  133.     Fileend = Filemem;
  134.     if ( readfile(Filename,Fileend,0) )
  135.         filemess("[New File]");
  136.     Topchar = Curschar = Filemem;
  137.  
  138.     updatescreen();
  139.     
  140.     edit();
  141.  
  142.     windexit(0);
  143. }
  144.  
  145. /*
  146.  * filetonext()
  147.  *
  148.  * Based on the current value of Topchar, transfer a screenfull of
  149.  * stuff from Filemem to Nextscreen, and update Botchar.
  150.  */
  151.  
  152. filetonext()
  153. {
  154.     int row, col;
  155.     char *screenp = Nextscreen;
  156.     char *memp = Topchar;
  157.     char *endscreen;
  158.     char *nextrow;
  159.     char extra[16];
  160.     int nextra = 0;
  161.     int c;
  162.     int n;
  163.  
  164.     /* The number of rows shown is Rows-1. */
  165.     /* The last line is the status/command line. */
  166.     endscreen = &screenp[(Rows-1)*Columns];
  167.  
  168.     row = col = 0;
  169.     while ( screenp < endscreen && memp < Fileend ) {
  170.  
  171.         /* Get the next character to put on the screen. */
  172.  
  173.         /* The 'extra' array contains the extra stuff that is */
  174.         /* inserted to represent special characters (tabs, and */
  175.         /* other non-printable stuff.  The order in the 'extra' */
  176.         /* array is reversed. */
  177.  
  178.         if ( nextra > 0 )
  179.             c = extra[--nextra];
  180.         else {
  181.             c = (unsigned)(0xff & (*memp++));
  182.             /* when getting a character from the file, we */
  183.             /* may have to turn it into something else on */
  184.             /* the way to putting it into 'Nextscreen'. */
  185.             if ( c == '\t' ) {
  186.                 strcpy(extra,"        ");
  187.                 /* tab amount depends on current column */
  188.                 nextra = (7 - col%8);
  189.                 c = ' ';
  190.             }
  191.             else if ( (n=chars[c].ch_size) > 1 ) {
  192.                 char *p;
  193.                 nextra = 0;
  194.                 p = chars[c].ch_str;
  195.                 /* copy 'ch-str'ing into 'extra' in reverse */
  196.                 while ( n > 1 )
  197.                     extra[nextra++] = p[--n];
  198.                 c = p[0];
  199.             }
  200.         }
  201.  
  202.         if ( c == '\n' ) {
  203.             row++;
  204.             /* get pointer to start of next row */
  205.             nextrow = &Nextscreen[row*Columns];
  206.             /* blank out the rest of this row */
  207.             while ( screenp != nextrow )
  208.                 *screenp++ = ' ';
  209.             col = 0;
  210.             continue;
  211.         }
  212.         /* store the character in Nextscreen */
  213.         if ( col >= Columns ) {
  214.             row++;
  215.             col = 0;
  216.         }
  217.         *screenp++ = c;
  218.         col++;
  219.     }
  220.     /* make sure the rest of the screen is blank */
  221.     while ( screenp < endscreen )
  222.         *screenp++ = ' ';
  223.     /* put '~'s on rows that aren't part of the file. */
  224.     if ( col != 0 )
  225.         row++;
  226.     while ( row < Rows ) {
  227.         Nextscreen[row*Columns] = '~';
  228.         row++;
  229.     }
  230.     Botchar = memp;
  231. }
  232.  
  233. /*
  234.  * nexttoscreen
  235.  *
  236.  * Transfer the contents of Nextscreen to the screen, using Realscreen
  237.  * to avoid unnecessary output.
  238.  */
  239.  
  240. nexttoscreen()
  241. {
  242.     char *np = Nextscreen;
  243.     char *rp = Realscreen;
  244.     char *endscreen;
  245.     char nc;
  246.     int row = 0, col = 0;
  247.     int gorow = -1, gocol = -1;
  248.  
  249.     endscreen = &np[(Rows-1)*Columns];
  250.  
  251.     for ( ; np < endscreen ; np++,rp++ ) {
  252.         /* If desired screen (contents of Nextscreen) does not */
  253.         /* match what's really there, put it there. */
  254.         if ( (nc=(*np)) != (*rp) ) {
  255.             *rp = nc;
  256.             /* if we are positioned at the right place, */
  257.             /* we don't have to use windgoto(). */
  258.             if ( ! (gorow == row && gocol == col) )
  259.                 windgoto(gorow=row,gocol=col);
  260.             windputc(nc);
  261.             gocol++;
  262.         }
  263.         if ( ++col >= Columns ) {
  264.             col = 0;
  265.             row++;
  266.         }
  267.     }
  268.     windrefresh();
  269. }
  270.  
  271. updatescreen()
  272. {
  273.     filetonext();
  274.     nexttoscreen();
  275. }
  276.  
  277. screenclear()
  278. {
  279.     int n;
  280.  
  281.     windclear();
  282.     /* blank out the stored screens */
  283.     for ( n=Rows*Columns-1; n>=0; n-- ) {
  284.         Realscreen[n] = ' ';
  285.         Nextscreen[n] = ' ';
  286.     }
  287. }
  288.  
  289. filealloc()
  290. {
  291.     if ( (Filemem=malloc((unsigned)FILELENG)) == NULL ) {
  292.         fprintf(stderr,"Unable to allocate %d bytes for file memory!\n",
  293.             FILELENG);
  294.         exit(1);
  295.     }
  296.     Filemax = Filemem + FILELENG;
  297. }
  298.  
  299. screenalloc()
  300. {
  301.     Realscreen = malloc((unsigned)(Rows*Columns));
  302.     Nextscreen = malloc((unsigned)(Rows*Columns));
  303. }
  304.  
  305. readfile(fname,fromp,nochangename)
  306. char *fname;
  307. char *fromp;
  308. int nochangename;    /* if 1, don't change the Filename */
  309. {
  310. #ifdef ATARI
  311.     static char currdisk = 0;
  312.     char fbuff[128];
  313.     int c1, c2;
  314. #endif
  315.     FILE *f;
  316.     char buff[128];
  317.     char *p;
  318.     int c, n;
  319.     int unprint = 0;
  320.  
  321. #ifdef ATARI
  322.     if ( currdisk == 0 )
  323.         currdisk = 'a' + Dgetdrv();
  324.  
  325.     /* If a drive is specified, it is used from then */
  326.     /* on as the default drive. */
  327.     c1 = tolower(*fname);
  328.     c2 = *(fname+1);
  329.     if ( c2 == ':' && c1>='a' && c1<='z' )
  330.         currdisk = c1;
  331.     else {
  332.         /* if no drive is specified, use the default one. */
  333.         sprintf(fbuff,"%c:%s",toupper(currdisk),fname);
  334.         fname = fbuff;
  335.     }
  336. #endif
  337.     if ( ! nochangename )
  338.         Filename = strsave(fname);
  339.  
  340. #ifdef ATARI
  341.     if ( (f=fopen(fname,Binary?"br":"r")) == NULL ) {
  342. #else
  343.     if ( (f=fopen(fname,"r")) == NULL ) {
  344. #endif
  345.         Fileend = Filemem;
  346.         return(1);
  347.     }
  348.  
  349.     for ( n=0; (c=getc(f)) != EOF; n++ ) {
  350.         if ( ! (isprint(c)||isspace(c)) )
  351.             unprint++;
  352.         if ( fromp >= Filemax ) {
  353.             fprintf(stderr,"File too long (limit is %d)!\n",FILELENG);
  354.             exit(1);
  355.         }
  356.         /* Insert the char at the current point by shifting
  357.         /* everything down. */
  358.         for ( p=Fileend; p>fromp; p-- )
  359.             *p = *(p-1);
  360.         *fromp++ = c;
  361.         if ( Fileend < fromp )
  362.             Fileend = fromp;
  363.     }
  364.     if ( ! Binary && unprint > 0 ) {
  365.         sprintf(buff,"%d unprintable chars!  Perhaps binary mode (-b) should be used?",unprint);
  366.         message(buff);
  367.         sleep(2);
  368.     }
  369.     if ( unprint > 0 )
  370.         p = "\"%s\" %d characters (%d un-printable)  (Press 'H' for help)";
  371.     else
  372.         p = "\"%s\" %d characters  (Press 'H' for help)";
  373.     sprintf(buff,p,fname,n,unprint);
  374.     message(buff);
  375.     fclose(f);
  376.     return(0);
  377. }
  378.  
  379. static char getcbuff[1024];
  380. static char *getcnext = NULL;
  381.  
  382. stuffin(s)
  383. char *s;
  384. {
  385.     if ( getcnext == NULL ) {
  386.         strcpy(getcbuff,s);
  387.         getcnext = getcbuff;
  388.     }
  389.     else
  390.         strcat(getcbuff,s);
  391. }
  392.  
  393. addtobuff(s,c1,c2,c3,c4,c5,c6)
  394. char *s;
  395. char c1, c2, c3, c4, c5, c6;
  396. {
  397.     char *p = s;
  398.     if ( (*p++ = c1) == '\0' )
  399.         return;
  400.     if ( (*p++ = c2) == '\0' )
  401.         return;
  402.     if ( (*p++ = c3) == '\0' )
  403.         return;
  404.     if ( (*p++ = c4) == '\0' )
  405.         return;
  406.     if ( (*p++ = c5) == '\0' )
  407.         return;
  408.     if ( (*p++ = c6) == '\0' )
  409.         return;
  410. }
  411.  
  412. vgetc()
  413. {
  414.     if ( getcnext != NULL ) {
  415.         int nextc = *getcnext++;
  416.         if ( *getcnext == '\0' ) {
  417.             *getcbuff = '\0';
  418.             getcnext = NULL;
  419.         }
  420.         return(nextc);
  421.     }
  422.     return(windgetc());
  423. }
  424.  
  425. vpeekc()
  426. {
  427.     if ( getcnext != NULL )
  428.         return(*getcnext);
  429.     return(-1);
  430. }
  431.  
  432. /*
  433.  * anyinput
  434.  *
  435.  * Return non-zero if input is pending.
  436.  */
  437.  
  438. anyinput()
  439. {
  440.     if ( getcnext != NULL )
  441.         return(1);
  442.     return(0);
  443. }
  444.  
  445. #ifdef ATARI
  446. sleep(n)
  447. int n;
  448. {
  449.     int k;
  450.  
  451.     k = Tgettime();
  452.     while ( Tgettime() <= k+n )
  453.         ;
  454. }
  455. #endif
  456.